const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const CompressionWebpackPlugin = require("compression-webpack-plugin");
const PreloadPlugin = require('@vue/preload-webpack-plugin');

const cssRules = /\.css$/; // 匹配css
const lessRules = /\.less$/; // 匹配less

// 抽取公共部分
const getStyleOptions = (importLoaders, loader) => {
    return [
        MiniCssExtractPlugin.loader,
        {
            loader: "css-loader",
            options: {
                importLoaders
            }
        },
        "postcss-loader",
        loader
    ].filter(Boolean);
}

module.exports = {
    // 生产环境
    mode: "production",
    // 入口
    entry: "./src/index.js",
    // 出口
    output: {
        path: path.resolve(__dirname, "lib"),
        // 使用contenthash 处理缓存问题
        filename: "js/[name].[contenthash:8].js",
        // 多入口时，会生成chunk文件
        chunkFilename: "js/[name].[contenthash:8].chunk.js",
        // 每次打包都清除之前的打包文件
        clean: true
    },
    // 配置loader
    module: {
        rules: [
            {
                // oneOf可以提供精准解析
                oneOf: [
                    {
                        test: cssRules,
                        use: getStyleOptions(1)
                    },
                    {
                        test: lessRules,
                        use: getStyleOptions(2, "less-loader")
                    },
                    {
                        test: /\.jsx?$/,
                        exclude: /node_modules/,
                        use: {
                            loader: "babel-loader",
                            options: {
                                // 开启缓存
                                cacheDirectory: true
                            }
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        // 通过import引入的样式会被单独打包成css文件
        new MiniCssExtractPlugin({
            filename: "css/[name].[contenthash:8].css",
            chunkFilename: "css/[name].[contenthash:8].css"
        }),
        // 进一步压缩
        new CompressionWebpackPlugin({
            exclude: /node_modules/,
        }),
        // 资源预获取
        new PreloadPlugin({
            rel: 'prefetch'
        })
    ],
    optimization: {
        // 开启压缩
        minimize: true,
        minimizer: [
            new CssMinimizerPlugin({
                exclude: /node_modules/,
                parallel: true
            }),
            new TerserPlugin({
                // node_modules不需要重复压缩
                exclude: /node_modules/,
                // 开启多进程压缩
                // 每打开一个进程，会额外耗时600ms左右，
                // 所以在大项目中效果会更好
                parallel: true,
                // 删除注释
                terserOptions: {
                    format: {
                        comments: false
                    }
                },
                extractComments: false
            })
        ],
        // 代码分割
        // 多入口时会使用chunk
        splitChunks: {
            chunks: "all"
        },
        runtimeChunk: {
            name: (entrypoint) => `runtime~${entrypoint.name}`
        }
    },
    resolve: {
        // 扩展文件名，引入时不需要写后缀
        extensions: [".jsx", ".js", ".json"]
    }
}